{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 上节问题回答"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 构建`Any`类型-`Any`类型定义"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`Any`类型概述 \n",
    "\n",
    "- 核心功能：可以接收任意数据类型的通用容器类，类似Java中的Object或Python中的基类\n",
    "- 设计动机：解决C++中任务返回值需要表示任意类型的问题，替代C++17标准库中的`Any`类型\n",
    "- 应用场景：主要用于线程池项目中任务返回值的通用存储"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`Any`类型实现细节\n",
    "\n",
    "- 基类指针技术：使用基类指针`(Base*)`指向派生类对象(Derive)，通过继承体系实现类型擦除\n",
    "- 智能指针选择：采用`std::unique_ptr`管理基类指针，避免裸指针的内存管理问题\n",
    "- 模板封装：派生类使用模板封装实际数据类型，实现类型安全的存储"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "基类与派生类设计 \n",
    "\n",
    "- 基类设计要点：\n",
    "  - 虚析构函数：必须声明为`virtual`，确保通过基类指针删除派生类对象时能正确调用派生类析构函数\n",
    "  - 默认实现：使用`= default`让编译器生成默认实现，优化代码效率\n",
    "- 派生类设计：\n",
    "  - 模板参数：派生类`Derive`是模板类，可以存储任意类型`T`的数据\n",
    "  - 数据封装：实际数据存储在派生类的`data_`成员变量中"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "构造函数与析构函数 \n",
    "\n",
    "- 构造函数设计：\n",
    "  - 模板构造函数：`Any(T data)`接收任意类型参数，内部用`make_unique`创建派生类对象\n",
    "  - 默认构造函数：显式声明`= default`避免潜在的编译错误\n",
    "- 拷贝控制：\n",
    "  - 禁用左值操作：删除拷贝构造函数和拷贝赋值运算符，遵循`unique_ptr`的独占语义\n",
    "  - 允许右值操作：默认实现移动构造函数和移动赋值运算符"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "模板与智能指针的应用 \n",
    "\n",
    "- 现代C++实践：\n",
    "  - `make_unique`：优先使用std`::make_unique`而非直接`new`，更安全高效\n",
    "  - 类型推导：模板自动推导参数类型，简化代码编写\n",
    "- 资源管理：\n",
    "  - 独占所有权：`unique_ptr`确保资源唯一所有权，防止内存泄漏\n",
    "  - 自动释放：智能指针在析构时自动释放资源，无需手动管理"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`Any`类型的巧妙设计 \n",
    "\n",
    "- 类型擦除技术：通过基类指针和模板派生类的组合，擦除具体类型信息\n",
    "- 多态存储：基类指针可以指向任意派生类实例，实现运行时多态\n",
    "- 类型安全：模板保证存储时类型正确，使用时需要显式转换"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`Any`类型的使用与注意事项 \n",
    "\n",
    "- 使用场景：\n",
    "  - 作为函数返回值容器，可以返回任意类型\n",
    "  - 需要类型擦除的通用数据存储场景\n",
    "- 注意事项：\n",
    "  - 类型转换：使用时需要显式转换为具体类型\n",
    "  - 性能考量：涉及动态内存分配，性能敏感场景需谨慎使用\n",
    "  - 异常安全：构造函数需要保证异常安全，使用`make_unique`有助于实现这一点"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 构建`Any`类型-Any类型应用 "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Any类型的设计原理\n",
    "\n",
    "- 多线程任务返回值问题：需要设计`run`函数的返回值能够表示任意类型，类似Java的Object基类或Python的Object基类功能。\n",
    "- C++17解决方案：使用Any类型作为通用返回值容器，通过基类指针和派生类模板实现类型擦除。\n",
    "- 存储机制：内部通过`std::unique_ptr<Base>`保存指向派生类`Derive<T>`的指针，在派生类中存储具体类型数据。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Any类型的接口设计\n",
    "\n",
    "- 构造函数设计：`Any(T data)`通过`make_unique`创建派生类对象，保存任意类型数据。\n",
    "- 类型安全转换：需要提供`cast_<T>()`方法将`Any`类型显式转换为具体类型，由使用者保证类型匹配。\n",
    "- 使用示例：任务返回`int`时，通过`res.get().cast_<int>()`获取具体值。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "线程池任务设计规范\n",
    "\n",
    "- 抽象基类要求：\n",
    "  - 必须继承自`Task`基类\n",
    "  - 必须重写纯虚函数`run()`\n",
    "  - `run()`返回值必须为`Any`类型\n",
    "- 用户自定义任务：\n",
    "  - 需要明确知道返回的具体类型\n",
    "  - 通过`cast_<T>()`进行安全类型转换\n",
    "  - 线程池仅负责调度不关心具体业务逻辑"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "实现细节与注意事项\n",
    "\n",
    "- 类型擦除原理：通过基类`Base`和模板派生类`Derive<T>`的组合实现，`Derive<T>`持有具体数据`data_`。\n",
    "- 线程安全考虑：\n",
    "  - 每个线程独立计算指定区间\n",
    "  - 需要显式等待线程完成(`std::this_thread::sleep_for`)\n",
    "  - 结果合并时要注意数据竞争\n",
    "- 典型错误：\n",
    "  - 忘记调用`cast_<>`进行类型转换\n",
    "  - 转换类型与实际存储类型不匹配\n",
    "  - 未正确处理线程生命周期"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 构建`Any`类型-Any转具体类型方法 "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Any类型介绍 \n",
    "\n",
    "- 功能特性：可以接收任意数据的类型，通过模板构造函数实现泛型存储\n",
    "- 存储原理：使用基类指针base_指向派生类对象`Derive`，实现类型擦除\n",
    "- 构造函数：`Any(T data) : base_(std::make_unique>(data))`，其中`T`为任意数据类型"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Any存储与提取数据 \n",
    "\n",
    "- 提取要求：必须显式指定目标类型，因为存储时类型信息已被擦除\n",
    "- 设计难点：需要从基类指针安全地还原出原始数据类型\n",
    "- 方法原型：模板方法`T cast_<T>()`，调用时需要指定具体类型如`cast_()`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "cast方法实现 \n",
    "\n",
    "- 核心步骤：\n",
    "  - 通过`base_.get()`获取基类裸指针\n",
    "  - 使用`dynamic_cast`进行向下转型\n",
    "  - 检查转换结果并返回数据\n",
    "- 类型安全：必须确保转换前后的类型匹配，否则会导致转换失败\n",
    "- 代码结构："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "基类与派生类指针转换 \n",
    "\n",
    "- 转换机制：使用运行时类型识别(RTTI)的`dynamic_cast`\n",
    "- 成功条件：基类指针必须实际指向目标派生类对象\n",
    "- 派生类设计：\n",
    "- 智能指针处理：通过`unique_ptr`的`get()`方法获取裸指针进行转换"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "类型识别与转换失败处理 \n",
    "\n",
    "- 错误场景：当`cast_<T>`指定的`T`与存储类型不符时\n",
    "  - 例如存储`int`但尝试用`cast_`提取\n",
    "- 异常处理：转换失败时抛出\"type is unmatch!\"异常\n",
    "- 正确返回：转换成功时通过`pd->data_`返回原始数据\n",
    "- 完整实现："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "功能验证 \n",
    "\n",
    "- 典型用法：\n",
    "- 验证要点：\n",
    "  - 类型转换的正确性\n",
    "  - 异常处理的完备性\n",
    "  - 多线程环境下的稳定性\n",
    "- 设计优势：通过类型擦除实现灵活的返回值处理，同时保证类型安全"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "C++17",
   "language": "C++17",
   "name": "xcpp17"
  },
  "language_info": {
   "name": "C++17"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
